import java.util.*;

public class TestBinaryTree {
    static class TreeNode {
        public char val;  //节点的值
        TreeNode left;   //左子树
        TreeNode right;  //右子树

        public TreeNode(char val) {
            this.val = val;
        }

    }
    public TreeNode createTree() {    //简单的创建一个树
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D= new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;
        return A;
    }

    public void preOrder(TreeNode root) {  //前序遍历
        if (root == null) {
            return;
        }
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    public void inOrder(TreeNode root) {   //中序遍历
        if (root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

    public void postOrder(TreeNode root) {   //后序遍历
        if (root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

    public int size(TreeNode root) {   //递归获取树中的节点数
        if (root == null) {
            return 0;
        }
        return 1+size(root.left)+size(root.right);
    }

    public int nodeSize;

    public void size2(TreeNode root) {  //遍历获取树中的节点数
        if (root == null) {
            return ;
        }
        nodeSize++;
        size2(root.left);
        size2(root.right);
    }

    public int getLeafNodeCount(TreeNode root) {  //获取树的叶子节点数
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        return  getLeafNodeCount(root.left)+getLeafNodeCount(root.right);
    }

    public int getKLeveNodeCount(TreeNode root,int k) {  //获取k层的节点数
        if (root == null) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        int leftTree = getKLeveNodeCount(root.left,k-1);
        int rightTree = getKLeveNodeCount(root.right,k-1);
        return leftTree + rightTree;
    }

    public int getTreeHeight(TreeNode root) {    //获取树的高度
        if (root == null) {
            return 0;
        }
        int leftHeight = getTreeHeight(root.left);
        int rightHeight= getTreeHeight(root.right);
        return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
    }

    public TreeNode find(TreeNode root,int val) {   //寻找树的一个节点
        if (root == null) {
            return null;
        }
        if (root.val == val) {
            return root;
        }
        TreeNode leftNode = find(root.left,val);
        if (leftNode != null) {
            return leftNode;
        }
        TreeNode rightNode = find(root.right,val);
        if (rightNode != null) {
            return rightNode;
        }
        return null;

    }

    public boolean isSameTree(TreeNode p,TreeNode q) {    //是否为相同树
        if (p == null && q != null) {
            return false;
        }
        if (p != null && q == null) {
            return false;
        }
        if (p == null && q == null) {
            return true;
        }
        if (p.val != q.val){
            return false;
        }
        boolean leftTree = isSameTree(p.left,q.left);
        boolean rightTree = isSameTree(p.right,q.right);
        return leftTree && rightTree;
    }

    public boolean isSubTree(TreeNode root,TreeNode subRoot) {  //是否为子树
        if (root == null || subRoot == null) {
            return false;
        }
        if (isSameTree(root,subRoot)) {
            return true;
        }
        if (isSubTree(root.left,subRoot)) {
            return true;
        }
        if (isSubTree(root.right,subRoot)) {
            return true;
        }
        return false;
    }

    public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true;
        }
        return isSymmetricChild(root.left,root.right);
    }

    public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) {
        if ((leftTree == null && rightTree != null) || (leftTree != null && rightTree == null)) {
            return false;
        }
        if (leftTree == null && rightTree == null) {
            return true;
        }
        if (leftTree.val != rightTree.val) {
            return false;
        }
        return isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right, rightTree.left);
    }

    public void levelOrder(TreeNode root) {  //层序遍历无返回值
        if (root == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root) ;
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            System.out.print(cur.val+" ");
            if (cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }
        }
    }

    public List<List<Character>> leveOrder2(TreeNode root) {  //层序遍历有返回值
        List<List<Character>> lists = new LinkedList<>();
        if (root == null) {
            return lists;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root) ;
        while (!queue.isEmpty()) {
            List<Character> list = new LinkedList<>();
            int size = queue.size();
            while (size != 0) {
                TreeNode cur = queue.poll();
//                System.out.print(cur.val+" ");
                list.add(cur.val);
                size--;
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            lists.add(list);
        }
        return lists;
    }

    public int i = 0;

    public  TreeNode createTree2(String str) {  //输入一串字符创建树
        TreeNode root = null;
        if (str.charAt(i) != '#') {
            root = new TreeNode(str.charAt(i));
            i++;
            root.left = createTree2(str);
            root.right = createTree2(str);
        }else {
            i++;
        }
        return root;
    }

    public int j = 0;

    public TreeNode buildTree(Character[] preorder,Character[] inorder) {
        return buildTreeChild(preorder,inorder,0,inorder.length);
    }

    public TreeNode buildTreeChild(Character[] preorder,Character[] inorder,int begin,int end) {
        if (begin > end) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[j]);
        int rootIndex = findIndex(inorder,begin,end,preorder[j]);
        j++;
        root.left = buildTreeChild(preorder,inorder,begin,rootIndex-1);
        root.right = buildTreeChild(preorder,inorder,rootIndex+1,end);
        return root;
    }

    public int findIndex(Character[] inorder,int begin,int end,Character key) {
        for (int k = begin ; k <= end; k++) {
            if (key.equals(inorder[k])) {
                return k;
            }
        }
        return -1;
    }

    public boolean isCompleteTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if (cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else {
                break;
            }
        }
        while (!queue.isEmpty()) {
            TreeNode tmp = queue.poll();
            if (tmp != null) {
                return false;
            }
        }
        return true;
    }

    public void preOrder2(TreeNode root) {  //前序遍历（不使用递归）
        if (root == null) {
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.val+" ");
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            cur = top.right;
        }
    }

    public void inOrder2(TreeNode root) {    //中序遍历（不使用递归）
        if (root == null) {
            return;
        }
        TreeNode cur= root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            System.out.print(top.val+" ");
            cur = top.right;
        }
    }

    public void postOrder2(TreeNode root) {  //后序遍历（不使用递归）
        if (root == null) {
            return;
        }
        TreeNode cur = root;
        TreeNode prev = null ;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek();
            if (top.right == null || prev == top.right ) {
                System.out.print(top.val+" ");
                stack.pop();
                prev = top;
            }else {
                cur = top.right;
            }
        }
    }
}
